package cn.gx.kevin.controller;

import cn.gx.kevin.common.ui.AdminControllerHelper;
import cn.gx.kevin.common.user.ILoginUserContext;
import cn.gx.kevin.common.utils.AESUtils;
import cn.gx.kevin.common.utils.RSAUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.gx.kevin.common.annotation.ApiDescript;
import cn.gx.kevin.common.annotation.ApiParams;
import cn.gx.kevin.common.annotation.ApiParamsDesc;
import cn.gx.kevin.common.annotation.ApiReturnDesc;
import cn.gx.kevin.common.ui.AjaxResult;
import cn.gx.kevin.common.user.LoginUser;
import cn.gx.kevin.common.utils.SysConfigParams;
import cn.gx.kevin.common.utils.SysConstants;
import cn.gx.kevin.domain.Menu;
import cn.gx.kevin.domain.Org;
import cn.gx.kevin.domain.User;
import cn.gx.kevin.service.*;
import cn.gx.kevin.service.IBaseService;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.*;

@Controller
@RequestMapping(value = "/v1")
public class DefaultController extends ResetfulBaseController<User, String> {

	@Resource(name = "dictService")
    IDictService dictService;

	IUserService userService;

	@Resource(name = "userService")
	@Override
	public void setService(IBaseService<User, String> service) {
		this.service = service;
		userService = (IUserService) service;
	}

	@Resource(name = "funcService")
    IFuncService funcService = null;

	@Resource(name = "userRoleService")
    IUserRoleService userRoleServie;

	@Resource(name = "menuService")
	IMenuService menuService;

	@Resource(name = "orgService")
	IOrgService orgService;

	private static Font mFont = new Font("Times New Roman", Font.PLAIN, 24);
	static int width = 80, height = 30;

	Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255) {
			fc = 255;
		}
		if (bc > 255) {
			bc = 255;
		}
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}

	@Override
	@RequestMapping(value = "/page/{pageName}", method = RequestMethod.GET)
	public String page(@PathVariable("pageName") String pageName, HttpServletRequest request) throws Exception {
        ILoginUserContext loginUserCtx = getLoginUserCtx();
		LoginUser user = loginUserCtx.getCurrentUser();
		if (user != null) { //已经登录了
			String systemIndex = SysConfigParams.getConfig("systemIndex");
			if(StringUtils.isEmpty(systemIndex) ){
				systemIndex = "index";
			}
			pageName = systemIndex;// 如果已经登录
			List<Object> listMenu = loginUserCtx.getUserMenus();
			List<Menu> menus = new ArrayList<>();
			for(Object obj : listMenu){
				menus.add((Menu)obj);
			}
			JSONArray json = menuService.getMenuJson("0", menus);
			request.setAttribute("menuJson", json);
			String userId = user.getId();
			request.setAttribute("loginUserId", userId);
			request.setAttribute("loginUser", user.getUserName());
			request.setAttribute("isAdmin", user.isSuperAdmin());
			request.setAttribute("account", user.getAccount());
			request.setAttribute("loginOrgId", user.getOrgId());
			request.setAttribute("loginOrg", user.getOrgName());
		}else{
			pageName = "login";
		}
		String publicKey = RSAUtils.getPublicKey();
		request.setAttribute("publicKey",publicKey);

		Calendar cal = Calendar.getInstance();
		int year = cal.get(Calendar.YEAR);
		request.setAttribute("year", year);
		return super.page(pageName, request);
	}

	@Override
	public String setPageModelPath(HttpServletRequest request) {
		return "";
	}


	@ApiDescript("根据公钥获取AES对称加密key")
	@RequestMapping(value = "/aeskey")
	public @ResponseBody
	AjaxResult getAesKey(HttpServletRequest request) throws Exception {
		String publicKey = request.getParameter("publicKey");
		byte [] publicBytes = Base64.decodeBase64(publicKey);
		String entryKey = SysConfigParams.getEntryKey();
		String privateKey = RSAUtils.getPrivateKey();
		byte [] clientKeys =  RSAUtils.decryptByPrivateKey(publicBytes,privateKey );
		String clientPublicKey =  new String( clientKeys);
		byte[] cipherKeyBytes = RSAUtils.encryptByPublicKey(entryKey.getBytes(),clientPublicKey);
		String chipherKey = Base64.encodeBase64String(cipherKeyBytes);
		return returnSuccData(chipherKey);
	}




	@ApiDescript("登出接口")
	@RequestMapping(value = "/logout")
	public @ResponseBody
    AjaxResult logout(HttpServletRequest request) throws Exception {
	    ILoginUserContext loginUserCtx = getLoginUserCtx();
		loginUserCtx.logout();
		return returnSuccess();
	}

	public JSONObject createImgCode(HttpServletRequest request) throws Exception {
		AjaxResult codeRes = getCode(request);
		JSONObject jOb = new JSONObject();
		jOb.put("imgKey", codeRes.message);
		jOb.put("img", codeRes.data);
		return jOb;
	}

	@ApiReturnDesc(value="{code:'0正确/1异常',message:'信息',data:'当验证码不对时候，为验证码base64数据，成功时候为token'}")
	@ApiParamsDesc(value="{userPwd:'密码(des加密)',userName:'账号',imgCode:'验证码',imgKey:'验证码key'}")
	@ApiParams(value="{userPwd:'',userName:'',imgCode:'',imgKey:''}")
	@ApiDescript("登录接口")
	@RequestMapping(value = "/login")
	public @ResponseBody AjaxResult login(HttpServletRequest request, HttpServletResponse response) throws Exception {
		//JSONObject prsObj = AdminControllerHelper.getParamFromEntityRequest(request);
		String imgCode = request.getParameter("imgCode");
		String imgKey = request.getParameter("imgKey");
        ILoginUserContext loginUserCtx = getLoginUserCtx();
		Object codeObj = loginUserCtx.getKeyValue(imgKey);
		loginUserCtx.deleteKeyValue(imgKey);
		String codeValid = SysConfigParams.getConfig("imageCodeValid");
		boolean imgCodeValid = codeValid == null || codeValid.equals("true");
		String token = "";
		if (imgCodeValid && codeObj == null) {
			return returnFailData(getLang("common_imgCodeExpDate"), createImgCode(request));
		} else {
			if (!imgCodeValid || imgCode.toLowerCase().equals(String.valueOf(codeObj))) {
				String userPwd = request.getParameter("userPwd");
				String userName = request.getParameter("userName");
				// 解密
				userPwd =  AESUtils.decrypt(userPwd);
				Map<String, Object> params = new HashMap<String, Object>();
				params.put("userName", userName);
				List<User> loginUsers = userService.selectParam(params);
				if (loginUsers.size() == 0) {
					return returnFailData(getLang("common_passWdErr"), createImgCode(request));
				} else {
					User user = loginUsers.get(0);
					if (user.getUserStatus().equals(0)) {
						return returnFailData(getLang("common_userforbit"), createImgCode(request));
					} else {
						String pwd = DigestUtils.md5Hex(userPwd);
						if (pwd.equals(user.getUserPwd())) {
                            loginUserCtx.deleteKeyValue(SysConstants.error_login_counter);
							LoginUser loginUser = loginUserCtx.loadUserAuthData(user);
							String orgId = loginUser.getOrgId();
							Org parentOrg = this.orgService.selectParentOrg(orgId);
							if(parentOrg != null){
								loginUser.setParentOrgId(parentOrg.getId());
								loginUser.setParentOrgName(parentOrg.getOrgName());
							}
							String key = loginUserCtx.setLoginUser(loginUser);
							if (StringUtils.isNotEmpty(key)) {
								token = loginUserCtx.writeLoginCookies(loginUser);
							} else {
								return returnFailData(getLang("common_nosetAuthor"), createImgCode(request));
							}
						} else {
							/*****密码连续错误超过loginTryCount次 则锁定账号******/
							Object tryCount =	SysConfigParams.getConfig("loginTryCount");
							if(tryCount != null) {
								int loginTryCount = Integer.parseInt( String.valueOf( tryCount) );
								if(loginTryCount > 0){
									int errCount = 1;
									Object err = loginUserCtx.getKeyValue(SysConstants.error_login_counter);
									if(err == null) {
                                        loginUserCtx.setKeyValue(SysConstants.error_login_counter, 0);
									}else {
										errCount = 	Integer.valueOf(String.valueOf(err)) + 1;
                                        loginUserCtx.setKeyValue(SysConstants.error_login_counter, errCount);
										if(errCount > loginTryCount && errCount < (loginTryCount + 3)) {
											User updateUser = new User();
											updateUser.setUserAccount(userName);
											updateUser.setUserStatus(0);
											userService.update(updateUser);
											return returnFailData(getLang("common_userforbit"));
										}
									}
									String message = getLang("common_passWdErr");
									if(errCount > 2) {
										String msg = getLang("common_login_error_count");
										message = msg.replace("x", String.valueOf(errCount) ).replaceFirst("y", String.valueOf(loginTryCount));
									}
									return returnFailData(message, createImgCode(request));
								}else{
									return returnFailData(getLang("common_passWdErr"), createImgCode(request));
								}
							}else {
								return returnFailData(getLang("common_passWdErr"), createImgCode(request));
							}
						}
					}
				}
			} else {
				return returnFailData(getLang("common_imgCodeErr"), createImgCode(request));
			}
		}
		return this.returnSuccData("login ok", token);
	}

/*	@ApiDescript("上传demo")
	@ApiParams("{}")
	@RequestMapping("/upload")
	public void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {
		super.upload(request, response);
	}*/

	/***
	 * 产生系统验证图片
	 ***/
	@ApiDescript("获取验证图片")
	@ApiReturnDesc("{code:'0正确/1异常',message:'验证码：服务器端imgKey',data:'验证码base64图片数据'}")
	@RequestMapping(value = "/getCode",method = RequestMethod.POST)
	public @ResponseBody AjaxResult getCode(HttpServletRequest request) throws Exception {

		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		Random random = new Random();
		g.setColor(getRandColor(200, 250));
		g.fillRect(1, 1, width - 1, height - 1);
		g.setColor(getRandColor(160, 200));
		// 画随机线
		for (int i = 0; i < 20; i++) {
			int x = random.nextInt(width - 1);
			int y = random.nextInt(height - 1);
			int z = random.nextInt(5);
			if (z < 2) {
				z = 2;
			}
			g.fillRoundRect(x, y, z, z, z / 2, z / 2);
		}
		g.setColor(new Color(14, 137, 204));
		g.drawRect(0, 0, width - 1, height - 1);
		g.setFont(mFont);
		// 生成随机数,并将随机数字转换为字母
		StringBuffer tmpBuffer = new StringBuffer();
		for (int i = 0; i < 4; i++) {
			int itmp = random.nextInt(26) + 65;
			char ctmp = (char) itmp;
			tmpBuffer.append(String.valueOf(ctmp));
			g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
			g.drawString(String.valueOf(ctmp), 15 * i + 8, 23);
		}
		String sRand = tmpBuffer.toString();
		g.dispose();
		ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
		ImageIO.write(image, "PNG", bout);
		Base64 base64 = new Base64();
		String imgBase64 = "data:image/png;base64," + base64.encodeAsString(bout.toByteArray());// 返回Base64编码过的字节数组字符串
		String imgKey = UUID.randomUUID().toString();
		ILoginUserContext loginUserCtx = getLoginUserCtx();
		loginUserCtx.setKeyValue(imgKey, sRand.toLowerCase());
		bout.close();
		return returnSuccData(imgKey, imgBase64);
	}



}
